/*
 * Copyright (C) 2013 rothens
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package rpg.ui.components;

import rpg.gfx.Bitmap;
import rpg.util.BoundingBox;
import rpg.util.MathUtil;

/**
 *
 * @author rothens
 */
public class ComponentScrollBar extends Component implements IClickableComponent, IDraggableComponent {

    public enum State {

        NONE,
        HOVER,
        DECREMENT,
        INCREMENT;
    }
    boolean dragged = false;
    boolean horizontal;
    boolean hasKnob = false;
    Bitmap truck;
    Bitmap knob;
    BoundingBox knobBB = null;
    State scrollState = State.NONE;
    int location = 0;
    int prev;
    ComponentButton decrement;
    ComponentButton increment;

    public ComponentScrollBar(Integer x, Integer y, int size) {
        this(x, y, size, false);
    }

    public ComponentScrollBar(Integer x, Integer y, int size, boolean horizontal) {
        super((horizontal) ? size : 16, (horizontal) ? 16 : size, x, y);
        this.horizontal = horizontal;
        Bitmap dec;
        Bitmap inc;
        Bitmap decarr;
        Bitmap incarr;
        if (horizontal) {
            dec = StaticTextures.hscroll[0];
            inc = StaticTextures.hscroll[1];
            decarr = StaticTextures.hscroll[6];
            incarr = StaticTextures.hscroll[7];
        } else {
            dec = StaticTextures.vscroll[0];
            inc = StaticTextures.vscroll[1];
            decarr = StaticTextures.vscroll[6];
            incarr = StaticTextures.vscroll[7];
        }

        decrement = new ComponentImageButton(0, 0,
                new Bitmap(dec).drawOn(decarr, 0, 0),
                new Bitmap(dec).drawOn(decarr.simpleRecolor(0xffffffff, 0xff0000), 0, 0),
                new Bitmap(dec).drawOn(decarr.simpleRecolor(0xffffffff, 0xffff00), 0, 0));
        increment = new ComponentImageButton((horizontal) ? width - inc.width : 0, (horizontal) ? 0 : height - inc.height,
                new Bitmap(inc).drawOn(incarr, 0, 0),
                new Bitmap(inc).drawOn(incarr.simpleRecolor(0xffffffff, 0xff0000), 0, 0),
                new Bitmap(inc).drawOn(incarr.simpleRecolor(0xffffffff, 0xffff00), 0, 0));

        truck = (horizontal) ? new Bitmap(width - decrement.width - increment.width, height, StaticTextures.hscroll[2])
                : new Bitmap(width, height - decrement.height - increment.height, StaticTextures.vscroll[2]);
    }

    @Override
    public void redraw() {
        clear();
        decrement.redraw();
        increment.redraw();
        if (horizontal) {
            draw(decrement, 0, 0);
            drawOn(increment, width - increment.width, 0);
            drawOn(truck, decrement.width, 0);
            if (hasKnob) {
                drawOn(knob, decrement.width + location, 0);
            }
        } else {
            draw(decrement, 0, 0);
            drawOn(increment, 0, height - increment.height);
            drawOn(truck, 0, decrement.height);
            if (hasKnob) {
                drawOn(knob, 0, decrement.height + location);
            }
            
        }
        if(parent != null){
            ((Component)parent).redraw();
        }

    }

    @Override
    public boolean onPress(int x, int y) {

        if (decrement.isMouseOver(x - this.x, y - this.y)) {
            scrollState = State.DECREMENT;
            if(hasKnob){
                location = Math.max(0, location - 5);
                redraw();
            }
            return true;
        } else if (increment.isMouseOver(x - this.x, y - this.y)) {
            scrollState = State.INCREMENT;
            if(hasKnob){
                location = Math.min((horizontal)?truck.width-knob.width:truck.height-knob.height, location + 5);
                redraw();
            }
            return true;            
        }

        return false;
    }

    @Override
    public boolean onRelease(int x, int y) {
        scrollState = State.NONE;
        redraw();
        return false;
    }

    @Override
    public void onStartDrag(int x, int y) {
        if(knob == null || !hasKnob){
            return;
        }
        x -= this.x;
        y -= this.y;
        if(knobBB.isMouseOver(x, y)){
            dragged = true;
            prev = (horizontal)?x-decrement.width:y-decrement.height;
        } else if(!decrement.isMouseOver(x, y) && !increment.isMouseOver(x, y)){
            dragged = true;
            if(horizontal){
                location = MathUtil.clamp(0, truck.width-knob.width, x-decrement.width);
                prev = x-decrement.width;
            } else {
                location = MathUtil.clamp(0, truck.height-knob.height, y-decrement.height);
                prev = y-decrement.height;
            }
            System.out.println(location);
        }
    }

    @Override
    public void whileDrag(int x, int y) {
        x -= this.x+decrement.width;
        y -= this.y+decrement.height;
        if(horizontal){
            if(prev == x){
                return;
            }
            final int diff = x - prev;
            location = MathUtil.clamp(0, truck.width-knob.width, location+diff);
            prev = x;
            redraw();
        } else {
            if(prev == y){
                return;
            }
            final int diff = y - prev;
            location = MathUtil.clamp(0, truck.height-knob.height, location+diff);
            prev = y;
            redraw();
        }
    }

    @Override
    public void onEndDrag(int x, int y) {
        updateBB();
        dragged = false;
        redraw();
    }

    @Override
    public boolean isDragged() {
        return dragged;
    }

    @Override
    public boolean isMouseOver(int x, int y) {
        boolean ret = super.isMouseOver(x, y);
        if (scrollState == State.NONE) {
            if (decrement.isMouseOver(x - this.x, y - this.y)) {
                decrement.setState(ComponentState.HOVER);
                increment.setState(ComponentState.INACTIVE);

            } else if (increment.isMouseOver(x - this.x, y - this.y)) {
                decrement.setState(ComponentState.INACTIVE);
                increment.setState(ComponentState.HOVER);

            } else {
                decrement.setState(ComponentState.INACTIVE);
                increment.setState(ComponentState.INACTIVE);

            }
        }

        return ret;
    }


    public void createKnob(int panelSize, int contentSize) {
        location = 0;
        if (contentSize <= panelSize) {
            knob = null;
            hasKnob = false;
            knobBB = null;            
        } else {
            int size = contentSize - panelSize;
            //System.out.println(ratio);
            hasKnob = true;
            if (horizontal) {
                int knobSize = Math.max(8, truck.width - size);
                knob = new Bitmap(knobSize, 16);
                knob.draw(StaticTextures.hscroll[3], -12, 0);
                knob.drawOn(StaticTextures.hscroll[5], knob.width - 4, 0);
                if (knobSize > 8) {
                    knob.drawOn(new Bitmap(knob.width - 8, 16, StaticTextures.hscroll[4]), 4, 0);
                }
            } else {
                int knobSize = Math.max(8, truck.height - size);
                knob = new Bitmap(16, knobSize);
                knob.draw(StaticTextures.vscroll[3], 0, -12);
                knob.drawOn(StaticTextures.vscroll[5], 0, knob.height - 4);
                if (knobSize > 8) {
                    knob.drawOn(new Bitmap(16, knob.height - 8, StaticTextures.vscroll[4]), 0, 4);
                }
            }
            updateBB();

            redraw();



        }
    }

    public void updateBB() {
        if (!hasKnob) {
            return;
        }
        if (knob == null) {
            return;
        }
        if (horizontal) {
            knobBB = new BoundingBox(decrement.width + location, 0, knob.width, knob.height);
        } else {
            knobBB = new BoundingBox(0, decrement.height + location, knob.width, knob.height);
        }
    }

    public int getLocation() {
        return location;
    }
}
